package com.dqx.utils;

import android.content.Context;
import android.content.res.Resources;
import android.opengl.GLES20;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

/**
 * OpenGL-ES工具类，主要用来加载着色器
 */
public class GLUtils {
    private static final String TAG = GLUtils.class.getName();

    /**
     * 创建着色器程序，并返回程序对象id
     *
     * @param context             上下文
     * @param vertexSourceRawId   顶点着色器的资源id
     * @param fragmentSourceRawId 片段着色器的资源id
     * @return
     */
    public static int buildProgram(Context context, int vertexSourceRawId, int fragmentSourceRawId) {
        return buildProgram(getStringFromRaw(context, vertexSourceRawId),
                getStringFromRaw(context, fragmentSourceRawId));
    }

    /**
     * 创建着色器程序，并返回程序对象id
     *
     * @param vertexSource
     * @param fragmentSource
     * @return 程序对象id
     */
    public static int buildProgram(String vertexSource, String fragmentSource) {
        //创建顶点着色器
        int vertexShader = buildShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {//创建失败
            return 0;
        }

        //创建片段着色器
        int fragmentShader = buildShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (fragmentShader == 0) {//创建失败
            return 0;
        }

        //创建程序
        int program = GLES20.glCreateProgram();
        if (program == 0) {
            return 0;
        }
        //将顶点着色器添加到程序中
        GLES20.glAttachShader(program, vertexShader);
        //将片段着色器添加到程序中
        GLES20.glAttachShader(program, fragmentShader);
        //连接程序
        GLES20.glLinkProgram(program);

        return program;
    }

    /**
     * 创建着色器，并返回着色器对象id
     *
     * @param type         创建类型
     * @param shaderSource 代码源
     * @return
     */
    public static int buildShader(int type, String shaderSource) {
        //创建着色器对象
        int shader = GLES20.glCreateShader(type);
        if (shader == 0) {//创建失败
            return 0;
        }
        //引入着色器代码源
        GLES20.glShaderSource(shader, shaderSource);
        //编译着色器
        GLES20.glCompileShader(shader);
        //着色器编译状态数组
        int[] status = new int[1];
        //获取着色器编译状态
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, status, 0);
        if (status[0] == 0) {//编译失败
            //打印着色器信息日志
            Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
            //删除着色器对象
            GLES20.glDeleteShader(shader);
            return 0;
        }

        return shader;
    }

    /**
     * 加载raw中的文件
     *
     * @param context 上下文
     * @param id      资源id
     * @return
     */
    public static String getStringFromRaw(Context context, int id) {
        String str;
        try {
            Resources r = context.getResources();
            InputStream is = r.openRawResource(id);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int i = is.read();
            while (i != -1) {
                baos.write(i);
                i = is.read();
            }
            str = baos.toString();
            is.close();
        } catch (IOException e) {
            str = "";
        }
        return str;
    }

    /**
     * 初始化缓存对象
     *
     * @param buffer
     * @return
     */
    public static FloatBuffer convertToFloatBuffer(float[] buffer) {
        FloatBuffer fb = ByteBuffer.allocateDirect(buffer.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        fb.put(buffer);
        fb.position(0);
        return fb;
    }
}
